<template>
    <el-container v-show="!editFile.show" style="user-select: none;height: 100%;">
        <el-header style="padding: 10px;">
            <el-row :gutter="10">
                <el-col :span="2" :sm="2" :md="2" :lg="2" :xl="2" style="justify-content: flex-end;">
                    <el-button-group>
                        <el-tooltip v-for="(item, id) in left_btns" effect="dark" :key="'left-btns' + id"
                            :content="item.text" placement="bottom">
                            <el-button :icon="item.ico" @click="item.click" :style="`width: ${100 / left_btns.length}%`"
                                :disabled="'enable' in item ? false : !path_list.length"
                                :loading="'have_load' in item ? loadding : false" />
                        </el-tooltip>
                    </el-button-group>
                </el-col>
                <el-col :span="15" :sm="10" :md="11" :lg="13" :xl="15" class="path">
                    <TouchInput v-model:content="input_path" :showIcon="true" @change="change_path">
                        <el-breadcrumb :separator-icon="ArrowRight" style="width: 100%;">
                            <el-breadcrumb-item><el-link>/</el-link></el-breadcrumb-item>
                            <el-breadcrumb-item v-for="item in path_list" :key="item.name">
                                <el-link>{{ item.name }}</el-link>
                            </el-breadcrumb-item>
                        </el-breadcrumb>
                    </TouchInput>
                </el-col>
                <el-col :span="3" :sm="5" :md="5" :lg="4" :xl="4">
                    <el-input v-model="search" style="width: 100%" placeholder="文件名" @keydown.enter="search_files">
                        <template #prepend>
                            <el-tooltip effect="dark" content="搜索" placement="bottom">
                                <el-button :icon="Search" @click="search_files" />
                            </el-tooltip>
                        </template>
                    </el-input>
                </el-col>
                <el-col :span="4" :sm="7" :md="6" :lg="5" :xl="3" style="justify-content: flex-start;">
                    <el-button-group>
                        <el-tooltip v-for="(item, id) in right_btns" effect="dark" :key="'right-btns' + id"
                            :content="item.text" placement="bottom">
                            <el-button :icon="item.ico" @click="item.click"
                                :disabled="'enable' in item ? false : !path_list.length"
                                :loading="'have_load' in item ? loadding : false" />
                        </el-tooltip>
                        <el-popconfirm v-if="select_file && path_list.length" confirm-button-text="确认"
                            cancel-button-text="取消" @confirm="delete_file"
                            :title="'是否删除 ' + select_file.name + ' ' + (select_file.type ? '文件' : '文件夹')">
                            <template #reference>
                                <el-button :icon="DeleteFilled" />
                            </template>
                        </el-popconfirm>
                    </el-button-group>
                    <input ref="file" type="file" style="display: none;" @change="upload(false)">
                    <input ref="folder" type="file" webkitdirectory style="display: none;" @change="upload(true)">
                </el-col>
            </el-row>
            <el-progress v-if='loaddingFile'
                :percentage="parseFloat((openFileReadSize * 100 / openFileSize).toFixed(2))" />
        </el-header>
        <el-main ref="fileSpan" style="padding: 0;" @click="change_select" v-loading="loadding"
            @dragover.prevent="fileSpanDragover" @dragleave.prevent="fileSpanDragleave" @drop.prevent="fileSpanDrop">
            <el-row :key="reload_files">
                <el-col v-for="(item, id) in folders" :key="id" :span="1.5">
                    <div class="folder" @dblclick="open_folder(item)" @mouseenter="changeInfoSelect(item)"
                        @mouseleave="changeInfoSelect(null)" @click.stop="(e) => change_select(e, item)">
                        <SvgIcon icon="folder" />
                        <TouchInput v-if="path_list.length" v-model:content="item.name" :rename="true" :blurChange="true"
                            @change="(new_name, old) => { file_rename(old, new_name) }">
                            <h4>{{ item.name }}</h4>
                        </TouchInput>
                        <h4 v-else>{{ item.name }}</h4>
                    </div>
                </el-col>
                <el-col v-for="(item, id) in files" :key="id" :span="1.5">
                    <div class="file" @dblclick="open_file(item)" @mouseenter="changeInfoSelect(item)"
                        @mouseleave="changeInfoSelect(null)" @click.stop="(e) => change_select(e, item)">
                        <img v-if="getFileImg(item.name)" :src="getFileImg(item.name)" />
                        <SvgIcon v-else :icon="get_file_ico(item.name)" />
                        <TouchInput v-if="path_list.length" v-model:content="item.name" :rename="true"
                            :blurChange="true" @change="(new_name, old) => { file_rename(old, new_name) }">
                            <h4>{{ item.name }}</h4>
                        </TouchInput>
                        <h4 v-else>{{ item.name }}</h4>
                    </div>
                </el-col>
            </el-row>
        </el-main>
        <el-footer class="footer" v-if="cur_select_file">
            <b>{{ cur_select_file.name }}</b>
            <b v-if="cur_select_file.path">{{ cur_select_file.path }}</b>
            <b v-if="cur_select_file.size">{{ size2str(cur_select_file.size) }}</b>
            <b v-if="cur_select_file.time">{{ new Date(cur_select_file.time).toLocaleString() }}</b>
        </el-footer>
    </el-container>
    <editor v-if="editFile.show" :contents="editFile.data" :title='editFile.name' :hex_mode="editFile.hex"
        @close="(data) => { editFile.show = false; console.log(data) }" @save="save_file" />
</template>
<script lang="ts">
const isTest = window.location.port.indexOf("51") !== -1
var file_manager_test_data = [
    { type: 0, name: "文件夹" },
    { type: 0, name: "文件夹112312312312312312" },
    { type: 1, name: "Zconfig.d", size: 4096 },
    { type: 1, name: "config.d", size: 4096 },
    { type: 1, name: "config1.d", size: 4096 },
    { type: 1, name: "config0.d", size: 4096 },
    { type: 1, name: "Aconfig.d", size: 4096 },
    { type: 1, name: "文件1", size: 1024 },
    { type: 1, name: "文件2.json", size: 2048 },
    { type: 1, name: "文件3.bin", size: 3072 },
    { type: 1, name: "文件4.txt", size: 4096 },
    { type: 1, name: "文件5.html", size: 10240 },
    { type: 1, name: "文件6.css", size: 20840 },
    { type: 1, name: "文件7.js", size: 1524 },
    { type: 1, name: "文件8.mp3", size: 512 },
    { type: 1, name: "文件9.png", size: 256 },
    { type: 1, name: "文件10.tar", size: 10240 },
    { type: 1, name: "文件11.doc", size: 4096 },
    { type: 1, name: "文件12.xml", size: 4096 },
    { type: 1, name: "文件13.csv", size: 4096 },
    { type: 1, name: "文件14.ppt", size: 4096 },
    { type: 1, name: "文件15.pdf", size: 4096 },
    { type: 1, name: "文件16.ttf", size: 4096 },
    { type: 1, name: "排序100.ttf", size: 4096 },
    { type: 1, name: "排序1.ttf", size: 4096 },
    { type: 1, name: "wifi.d", size: 4096 },
    { type: 1, name: "bt.d", size: 4096 },
]
if (!isTest)
    file_manager_test_data = []
</script>
<script setup lang="ts">
import { ArrowRight, ArrowLeft, Refresh, Search, Download, Plus, FolderAdd, Upload, UploadFilled, DeleteFilled } from '@element-plus/icons-vue'
import Bus from "~/utils/bus";
import editor from './editor.vue';
import file_api from './device_api.ts'
import { ElMessage, ElMessageBox, ElButtonGroup, ElButton } from 'element-plus'
import "element-plus/es/components/button-group/style/css"
import "element-plus/es/components/message/style/css"
import "element-plus/es/components/message-box/style/css"
interface data_item {
    type: number,
    name: string,
    size: number,
    time?: number,
    path?: string,
    value?: any,
}
interface result_msg {
    api: string,
    data: data_item[] | number | object
}
/* 文件后缀对应的图标 */
const files_ico = [
    { name: ["png", "jpg", "jpeg", "ico", "svg"], ico: 'picture' },
    { name: ["json"], ico: 'json' },
    { name: ["bin"], ico: 'blob' },
    { name: ["txt"], ico: 'txt' },
    { name: ["d"], ico: 'config' },
    { name: ["css"], ico: 'css' },
    { name: ["js"], ico: 'js' },
    { name: ["xml"], ico: 'xml' },
    { name: ["pdf"], ico: 'pdf' },
    { name: ["mp3", "pcm", "aac", "wav", "flac"], ico: 'music' },
    { name: ["ppt"], ico: 'ppt' },
    { name: ["htm", "html"], ico: 'html' },
    { name: ["ttf", "otf", "woff", "woff2", "eot"], ico: 'ttf' },
    { name: ["doc", "docx", "docm", "dotx", "dotm", "dot"], ico: 'word' },
    { name: ["xls", "xlsx", "xlsm", "xlsb", "xlt", "xla", "csv"], ico: 'xlsx' },
    { name: ["zip", "gz", "tar", "tar.gz", "rar", "xz", "7z", "bzip2", "gzip", "wim"], ico: 'zip' },
]

function get_file_ico(name: string) {
    let arr = name.split(".")
    let ext = arr[arr.length - 1]
    for (let item of files_ico) {
        for (let ext_item of item.name)
            if (ext_item == ext)
                return item.ico
    }
    return "file"
}

const props = defineProps({
    datas: {
        type: Array<data_item>,
        default: file_manager_test_data
    }
})

let next_path = '/'
const path = ref("/")
const input_path = ref("/")
const data = toRef(props.datas)
const search = ref('')
const reload_files = ref(0)
const loadding = ref(true)
const editor_show = ref(true)
const search_list: any = ref([])
const cur_select_file: data_item = ref(null)
const select_file: any = ref(null)
const fileSpan = ref(null)
const file = ref(null)
const folder = ref(null)
const imgCache = ref({})
const loaddingFile = ref(false)
let openFilePath = ''
let openFileSize = 0;
let openFileReadSize = ref(0)
let openFileStream = new Blob([""])
const editFile = reactive({
    show: false,
    hex: false,
    name: '',
    data: new Uint8Array(0),
    path: '',
})

const left_btns = [
    { text: "返回", ico: ArrowLeft, click: back },
    { text: "刷新", ico: Refresh, click: refresh, enable: 1, have_load: 1 },
]
const right_btns = [
    { text: "创建文件", ico: Plus, click: () => { openInputName(false) } },
    { text: "创建文件夹", ico: FolderAdd, click: () => { openInputName(true) } },
    { text: "上传文件", ico: Upload, click: () => { file.value?.click() } },
    { text: "上传文件夹", ico: UploadFilled, click: () => { folder.value?.click() } },
]

function name_sort(a: any, b: any) {
    let a_name = a.name.split(".")[0]
    let b_name = b.name.split(".")[0]
    let a_word_name = a_name.match(/[^\x00-\xff]/g)
    let b_word_name = b_name.match(/[^\x00-\xff]/g)
    let a_byte_name = a_name.match(/[\x00-\xff]/g)
    let b_byte_name = b_name.match(/[\x00-\xff]/g)
    // console.log(a, b, a_word_name, b_word_name)
    if (a_word_name && !b_word_name)
        return -1;
    if (!a_word_name && b_word_name)
        return 1;
    if (!a_word_name && !b_word_name)
        return a_name.localeCompare(b_name)
    if (a_word_name.length)
        a_word_name = a_word_name.join("")
    if (b_word_name.length)
        b_word_name = b_word_name.join("")
    // console.log(a_word_name, a_word_name.length, b_word_name, b_word_name.length)
    if (a_word_name.length != b_word_name.length)
        return a_word_name.length - b_word_name.length;
    let result = a_word_name.localeCompare(b_word_name)
    // console.log(result, a_word_name.length - b_word_name.length, a, b)
    if (result == 0) {/* 双字节相同 */
        /* 对比单字节内容 */
        if (a_byte_name && b_byte_name) {
            if (a_byte_name.length != b_byte_name.length)
                return a_byte_name.length - b_byte_name.length
            return a_byte_name.join("").localeCompare(b_byte_name.join(""))
        }
    }
    return result/* 双字节字符排序 */
}

const folders = computed(() => {
    let arr: any[] = []
    if (search_list.value.length)
        for (let item of search_list.value) {
            if (item.type == 0) {
                arr.push(item)
            }
        }
    else
        for (let item of data.value) {
            if (item.type == 0) {
                arr.push(item)
            }
        }
    return arr.sort(name_sort)
})

const files = computed(() => {
    let arr: any[] = []
    if (search_list.value.length)
        for (let item of search_list.value) {
            if (item.type == 1) {
                arr.push(item)
            }
        }
    else
        for (let item of data.value) {
            if (item.type == 1) {
                arr.push(item)
            }
        }
    return arr.sort(name_sort)
})

const path_list = computed(() => {
    let arr = path.value.split("/")
    let list: any[] = []
    for (let i = 0; i < arr.length; i++) {
        if (arr[i] == "")
            continue
        let path = arr.slice(0, i + 1).join("/")
        list.push({ name: arr[i], path: path })
    }
    return list
})

/* 👇👇👇👇👇👇 内部API 👇👇👇👇👇👇 */
function get_path(path: string, name: string) {
    let cur_path = path + '/' + name;
    cur_path = cur_path.replace("//", "/");
    return cur_path;
}

function size2str(size: number) {
    if (size < 1024) {
        return size + "B"
    } else if (size < 1024 * 1024) {
        return (size / 1024).toFixed(2) + "KB"
    } else if (size < 1024 * 1024 * 1024) {
        return (size / 1024 / 1024).toFixed(2) + "MB"
    } else {
        return (size / 1024 / 1024 / 1024).toFixed(2) + "GB"
    }
}

function getFileImg(name) {
    let is_img = false;
    for (let item of files_ico[0].name) {
        if (name.indexOf(item) != -1) {
            is_img = true;
            break;
        }
    }
    if (!is_img)
        return false

    let cur_path = get_path(path.value, name);
    if (cur_path in imgCache.value) {
        return imgCache.value[cur_path].icon
    }

    return false
}

function changeInfoSelect(item: data_item | null) {
    if (item)
        cur_select_file.value = item
    else
        cur_select_file.value = select_file.value
}

function change_select(e: MouseEvent, item: data_item | undefined) {
    if (cur_select_file && cur_select_file.value == select_file.value)
        cur_select_file.value = null;
    select_file.value = null;
    document.querySelectorAll(".select").forEach((item) => {
        item.classList.remove("select")
    })
    let target: any = e.target
    while (target.localName != 'div') {
        target = target.parentElement
        if (!target)
            return;
    }
    if (!target.classList.contains("el-row")) {
        target.classList.add("select")
        if (item)
            select_file.value = item
    }
}

/* 👇👇👇👇👇👇 拖拽上传 👇👇👇👇👇👇 */
function fileSpanDragover(e: any) {
    e.target.style.backgroundColor = "aliceblue";
}

function fileSpanDragleave(e: any) {
    e.target.style.backgroundColor = "";
}

function fileSpanDrop(e: any) {
    e.target.style.backgroundColor = "";
    if (!path_list.value.length) {
        ElMessage.error('根目录不允许上传文件/文件夹')
        return;
    }
    var items = e.dataTransfer.items;
    let file_list = [];
    for (var i = 0; i < items.length; i++) {
        var item = items[i].webkitGetAsEntry();
        if (item) {
            if (item.isDirectory) {
                let files_list = [];
                let reader = item.createReader();
                reader.readEntries((entries: any) => {
                    for (let i = 0; i < entries.length; i++) {
                        entries[i].file((file: any) => {
                            files_list.push(file);
                            if (files_list.length == entries.length) {
                                upload(true, item.name + "/", files_list);
                            }
                        });
                    }
                });
            } else file_list.push(e.dataTransfer.files[i]);
        }
    }
    if (file_list.length) upload(true, "", file_list);
}
/* 👆👆👆👆👆👆 拖拽上传 👆👆👆👆👆👆 */

function back() {
    console.log("back", path.value)
    if (search_list.value.length) {
        search_list.value.splice(0, search_list.value.length)
        return;
    }
    next_path = path.value.split("/").slice(0, -1).join("/");
    if (!next_path.length)
        next_path = "/"
    Bus.emit('push.msg', { api: "get_files", data: { path: next_path } })
    loadding.value = true
}

function refresh() {
    console.log("refresh")
    file_api.get_dir(path.value)
}

function search_files() {
    console.log("search", search.value)
    file_api.search(path.value, search.value)
    loadding.value = true
}

function openInputName(isDir: Boolean) {
    ElMessageBox.prompt('请输入名称', '新建' + (isDir ? "文件夹" : "文件"), {
        confirmButtonText: '确认',
        cancelButtonText: '取消',
    })
        .then(({ value }) => {
            let _path = get_path(path.value, value);
            file_api.create(_path, isDir);
            ElMessage({
                type: 'success',
                message: `成功创建 ${value} ${isDir ? "文件夹" : "文件"}`,
            })
            refresh();
        })
        .catch(() => {
        })
}

async function upload(isFolder: Boolean, extern_path = "", folder_i = folder.value?.files) {
    let upload_files = [];
    console.log(folder_i);
    let cur_path = get_path(path.value, "");
    if (!isFolder) {
        const files = file.value?.files
        if (files.length)
            upload_files.push({
                path: cur_path + files[0].name,
                file: files[0],
            });
    } else {
        if (folder_i.length) {
            let path = "";
            for (let i = 0; i < folder_i.length; i++) {
                if (folder_i[i].webkitRelativePath !== "") {
                    path = cur_path + folder_i[i].webkitRelativePath;
                } else {
                    path = cur_path + extern_path + folder_i[i].name;
                }
                upload_files.push({ path: path, file: folder_i[i] });
            }
        }
    }

    for (let i = 0; i < upload_files.length; i++) {
        let cur_file = upload_files[i];
        await file_api.upload(cur_file);
    }

    refresh()
}

function delete_file() {
    ElMessage({
        type: 'success',
        message: `成功删除 ${select_file.value?.name} ${select_file.value?.type ? "文件" : "文件夹"}`,
    })
    let _path = get_path(path.value, cur_select_file.value.name);
    file_api.delete(_path, !select_file.value?.type);
    refresh()
}

function change_path(path: String) {
    console.log("change_path", path)
    file_api.get_dir(path)
    next_path = path
    loadding.value = true
}

function open_folder(item: data_item) {
    let _path = get_path(path.value, item.name);
    console.log("open_folder", _path)
    change_path(_path)
}

function open_file(item: data_item) {
    let _path = ''
    if (item.path)
        _path = item.path
    else
        _path = get_path(path.value, item.name);
    openFilePath = _path
    console.log("open_file", openFilePath)
    const cache = imgCache.value[openFilePath]
    console.log(cache)
    if (!cache)
        file_api.get(openFilePath, 0)
    else
        showOpenFileMessageBox(item.name, cache.data)
}

async function save_file(data: Uint8Array) {
    await file_api.upload({ path: openFilePath, file: new Blob([data]) })
}

function file_rename(item, new_name) {
    let _path = path.value + '/'
    if (typeof item == 'object')
        _path = get_path(path.value, item.name);
    else
        _path = get_path(path.value, item);
    let new_path = get_path(path.value, new_name);
    console.log("file_rename", _path, new_path)
    file_api.rename(_path, new_path)
}

function download_file(name, data) {
    let a = document.createElement('a');
    a.href = URL.createObjectURL(data);
    a.download = name;
    a.click();
    URL.revokeObjectURL(a.href);
}

function showOpenFileMessageBox(name: String | any, data: Blob) {
    let msgbox = ElMessageBox({
        title: '文件已加载, 请选择以下方式',
        showConfirmButton: false,
        message: () =>
            h(ElButtonGroup, null, {
                default: () => [
                    h(ElButton, {
                        type: 'primary',
                        onClick: () => {
                            if (typeof name == 'string')
                                download_file(name, data)
                            else
                                download_file(name.value.name, data)
                        },
                    }, { default: () => '下载' }),
                    h(ElButton, {
                        type: 'primary',
                        onClick: () => {
                            data.arrayBuffer().then(buffer => {
                                editFile.data = new Uint8Array(buffer);
                                if (typeof name == 'string')
                                    editFile.name = name;
                                else
                                    editFile.name = name.value.name;
                                editFile.path = openFilePath;
                                editFile.show = true;
                                editFile.hex = false;
                                const btn = document.querySelector(".el-message-box__headerbtn")
                                if (btn)
                                    btn.click()
                            })
                        },
                    }, { default: () => '文本 编辑' }
                    ),
                    h(ElButton, {
                        type: 'primary',
                        onClick: () => {
                            data.arrayBuffer().then(buffer => {
                                editFile.data = new Uint8Array(buffer);
                                if (typeof name == 'string')
                                    editFile.name = name;
                                else
                                    editFile.name = name.value.name;
                                editFile.path = openFilePath;
                                editFile.show = true;
                                editFile.hex = true;
                                const btn = document.querySelector(".el-message-box__headerbtn")
                                if (btn)
                                    btn.click()
                            })
                        },
                    }, { default: () => 'HEX 仅查看' }
                    ),
                    h(ElButton, {
                        type: 'primary',
                        onClick: () => {
                            file_api.get(openFilePath, 0)
                            const btn = document.querySelector(".el-message-box__headerbtn")
                            if (btn)
                                btn.click()
                        },
                    }, { default: () => '重新缓存' }
                    )
                ]
            }),
    }).catch(() => {
    })
}

function file_load(data: Blob) {
    let is_img = false;
    let img_type = ''
    for (let item of files_ico[0].name) {
        if (openFilePath.indexOf(item) != -1) {
            is_img = true;
            img_type = item;
            break;
        }
    }
    let reader = new FileReader();
    if (img_type != 'png' && is_img)
        reader.readAsText(data);
    else
        reader.readAsDataURL(data);
    reader.onload = function () {
        console.log(reader.result)
        if (img_type != 'png' && is_img)
            imgCache.value[openFilePath] = { icon: `data:image/${img_type}+xml;base64,` + btoa(reader.result), data };
        else
            imgCache.value[openFilePath] = { icon: reader.result, data };
    }
    ElMessage({
        type: 'success',
        message: `数据已缓存 ${is_img ? ", 再次双击可唤出操作窗" : ''}`,
    })
    console.log(`cache ${openFilePath} data`)
    if (!is_img)
        showOpenFileMessageBox(cur_select_file, data)
}

onBeforeUnmount(() => {
    Bus.off("update:msg", get_file_manager_msg)
    Bus.off("update:stream", get_file_stream_msg)
});

onBeforeMount(() => {
    Bus.on("update:msg", get_file_manager_msg);
    Bus.on("update:stream", get_file_stream_msg);
    file_api.get_dir(path.value)
});
/* 👆👆👆👆👆👆 内部API 👆👆👆👆👆👆 */


/* 👇👇👇👇👇👇 设备API 👇👇👇👇👇👇 */
function get_file_manager_msg(result: result_msg) {
    if (result.api == "get_files") {
        if (typeof result.data != "number") {
            data.value = result.data;
            path.value = next_path;
            input_path.value = next_path;
            cur_select_file.value = null;
            select_file.value = null;
            reload_files.value++
        }
        loadding.value = false;
    } else if (result.api == "get_files_search") {
        if (typeof result.data != "number") {
            search_list.value.splice(0, search_list.value.length);
            for (let i = 0; i < result.data.length; i++)
                search_list.value.push(result.data[i]);
            if (search_list.value.length == 0) {
                ElMessage({
                    message: "搜索结果为0",
                    type: "warning",
                    plain: true,
                });
            }
        }
        loadding.value = false;
    } else if (result.api == "get_file") {
        loaddingFile.value = true;
        openFileStream = new Blob([]);
        openFileSize = result.data.size;
        openFileReadSize.value = 0;
        console.log(openFileSize, openFileSize == 0)
        if (openFileSize == 0) {
            showOpenFileMessageBox(cur_select_file, openFileStream)
            loaddingFile.value = false;
        }
    } else if (result.api == "change_file") {
        if (result.data == -1) {
            ElMessage({
                message: "文件不存在",
                type: "error",
                plain: true,
            });
        } else if (result.data == 1) {
            ElMessage({
                message: "文件保存成功",
                type: "success",
                plain: true,
            });
        }
    }
}

function mergeBlobs(blobs: Array<Blob>) {
    const sizes: Array<any> = [];
    blobs.forEach(blob => {
        sizes.push(blob.size);
    });
    // 获取总大小
    const totalSize = sizes.reduce((total, size) => total + size, 0);
    // 创建新的Blob对象
    const blob = new Blob(blobs);
    // 如果需要，可以创建一个用于截断的Blob视图
    const blobWithCorrectSize = blob.slice(0, totalSize);
    return blobWithCorrectSize;
}
function get_file_stream_msg(result: Blob) {
    if (openFileSize) {
        openFileStream = mergeBlobs([openFileStream, result])
        openFileReadSize.value += result.size
        console.log(openFileReadSize.value, openFileSize, (openFileReadSize.value / openFileSize * 100).toFixed(2))
        if (openFileStream.size == openFileSize || openFileReadSize.value == openFileSize) {
            // console.log(openFileStream)
            file_load(openFileStream)
            openFileSize = 0;
            loaddingFile.value = false;
        }
    }
}
/* 👆👆👆👆👆👆 设备API 👆👆👆👆👆👆 */
</script>

<style scoped>
.path {
    padding: 10px !important;
    border-radius: 10px;
    border: #00000024 1px solid;
}

.footer {
    bottom: 0;
    padding: 0;
    padding-bottom: 10px;
    width: 100%;
    height: auto;
    position: absolute;
    display: flex;
    justify-content: space-evenly;
}

.folder,
.file {
    position: relative;
    border-radius: 10px;
    width: 74px;
    padding: 10px;
    margin: 1px;
    display: flex;
    align-items: center;
    flex-flow: column nowrap;
}

.folder:hover,
.file:hover,
.select {
    background-color: #767e8563;
}

.folder h4,
.file h4 {
    margin: 0;
    text-align: center;
    width: 74px;
    height: 25px;
    text-overflow: ellipsis;
    overflow: hidden;
    white-space: nowrap;
}

.folder svg,
.file svg,
.file img {
    width: 4em;
    height: 4em;
}
</style>